package com.example.springboot.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.simple.SimpleDataSource;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.example.springboot.dto.CodeGeneratorDto;
import com.example.springboot.entity.TableColumn;
import com.example.springboot.entity.VueMap;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * mp代码生成器
 */
public class CodeGeneratorNew {
    // ----------------------------------------以下必须修改------------------------------------------

    private static final String basePath = System.getProperty("user.dir");

    // ----------------------------------------以上必须修改-----------------------------------------

    private static final String url = "jdbc:mysql://localhost:3306/";
    private static final String username = "root";

    public static void main(String[] args) throws Exception {

        // 生成SpringBoot
//        generate(tableName);
//        // 生成vue
//        createVue(tableName);
//        // 生成菜单
//        createMenu(tableName, modelName);
    }


    public static void generateAll(CodeGeneratorDto dto) throws Exception {
        if ("true".equals(dto.getIsGenerateJava())) {
            generate(dto);
        }
        if ("true".equals(dto.getIsGenerateVue())) {
            //生成vue
            createVue(dto);
        }
        if ("true".equals(dto.getIsGenerateMenu())) {
            // 生成菜单
            createMenu(dto);
        }
    }

    /**
     * s
     * 生成SpringBoot文件
     */
    private static void generate(CodeGeneratorDto dto) {

        FastAutoGenerator.create(url + dto.getDataSource(), username, dto.getPassword())
                .globalConfig(builder -> {
                    builder.author("cpf") // 设置作者
                            .commentDate("")
                            .enableSwagger()
                            .fileOverride() // 覆盖已生成文件
                            .disableOpenDir()
                            .outputDir(basePath + "/springboot/src/main/java/"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.example.springboot") // 设置父包名
                            .moduleName(null) // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, basePath + "/springboot/src/main/resources/mapper/")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
//                    builder.entityBuilder().enableLombok();//取消使用lombok生成实体类
//                    builder.mapperBuilder().enableMapperAnnotation().build();
                    builder.mapperBuilder().enableBaseColumnList();//开启通用查询结果列配置
                    builder.mapperBuilder().enableBaseResultMap();//开启resultMap映射
                    builder.controllerBuilder().enableHyphenStyle()  // 开启驼峰转连字符
                            .enableRestStyle();  // 开启生成@RestController 控制器
                    builder.addInclude(dto.getTableName()) // 设置需要生成的表名
                            .addTablePrefix("t_", "sys_"); // 设置过滤表前缀
                })
//                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                .execute();

    }

    /**
     * 生成vue文件
     */
    private static void createVue(CodeGeneratorDto dto) throws Exception {
        String lowerEntityName = StrUtil.toCamelCase(dto.getTableName().replace("sys_", "").replace("t_", ""));
        String upperEntityName = StrUtil.upperFirst(lowerEntityName);
        String space6 = "      ";
        String space8 = "        ";
        String space10 = "          ";
        StringBuilder tableColumnBuilder = new StringBuilder();
        StringBuilder formItemBuilder = new StringBuilder();
        List<TableColumn> tableColumns = getTableColumns(dto);
        tableColumnBuilder.append(space6).append("<el-table-column label=\"序号\" type=\"index\" width=\"50\" align=\"center\"></el-table-column>");

        for (TableColumn tableColumn : tableColumns) {
            //id,操作日期，创建日期不展示
            if (tableColumn.getName().equals("id") || tableColumn.getName().contains("time")) {
                continue;
            }
            String camelCaseName = StrUtil.toCamelCase(tableColumn.getName());
            // 生成表格
            if (tableColumn.getName().endsWith("img") || tableColumn.getName().equals("avatar_url") || tableColumn.getName().contains("avatar")) {
                tableColumnBuilder.append(space6).append("<el-table-column label=\"图片\"><template slot-scope=\"scope\"><el-image style=\"width: 100px; height: 100px\" :src=\"scope.row.").append(camelCaseName).append("\" :preview-src-list=\"[scope.row.").append("img]\"></el-image></template></el-table-column>\n");
            } else if (tableColumn.getName().endsWith("file")) {
                tableColumnBuilder.append(space6).append("<el-table-column label=\"文件\"><template slot-scope=\"scope\"><el-button type=\"primary\" @click=\"download(scope.row.").append(camelCaseName).append(")\">下载</el-button></template></el-table-column>\n");
            } else if (tableColumn.getName().contains("_id")) {
                tableColumnBuilder.append(space6).append("<el-table-column prop=\"").append(camelCaseName).append("\" label=\"").append(tableColumn.getComment()).append("\" align=\"center\" v-if=\"false\"></el-table-column>\n");
            } else {
                tableColumnBuilder.append(space6).append("<el-table-column prop=\"").append(camelCaseName).append("\" label=\"").append(tableColumn.getComment()).append("\" align=\"center\"></el-table-column>\n");
            }
            StringBuilder formBuilder = formItemBuilder.append(space8).append("<el-form-item prop=\"").append(camelCaseName).append("\" label=\"").append(tableColumn.getComment()).append("\">\n");
            if (tableColumn.getName().contains("time")) {
                // 日期时间
                formBuilder.append(space10).append("<el-date-picker v-model=\"ruleForm.").append(camelCaseName).append("\" type=\"datetime\" value-format=\"yyyy-MM-dd HH:mm:ss\" placeholder=\"选择日期时间\"></el-date-picker>\n");
            } else if (tableColumn.getName().endsWith("date")) {
                // 日期
                formBuilder.append(space10).append("<el-date-picker v-model=\"ruleForm.").append(camelCaseName).append("\" type=\"date\" value-format=\"yyyy-MM-dd\" placeholder=\"选择日期\"></el-date-picker>\n");
            } else if (tableColumn.getName().endsWith("file")) {
                // 文件上传
                formBuilder.append(space10).append("<el-upload action=\"http://localhost:9090/file/upload\" ref=\"file\" :on-success=\"handleFileUploadSuccess\">\n");
                formBuilder.append(space10).append("  <el-button size=\"small\" type=\"primary\">点击上传</el-button>\n");
                formBuilder.append(space10).append("</el-upload>\n");
            } else if (tableColumn.getName().endsWith("img") || tableColumn.getName().equals("avatar_url") || tableColumn.getName().contains("avatar")) {
                // 文件上传
                formBuilder.append(space10).append("<el-upload action=\"http://localhost:9090/file/upload\" ref=\"img\" :on-success=\"handleImgUploadSuccess\">\n");
                formBuilder.append(space10).append("  <el-button size=\"small\" type=\"primary\">点击上传</el-button>\n");
                formBuilder.append(space10).append("</el-upload>\n");
            }else if(tableColumn.getName().contains("_id")){
                formBuilder.append(space10).append("<el-input v-if='false' v-model=\"ruleForm.").append(camelCaseName).append("\" autocomplete=\"off\"></el-input>\n");
            }
            else {
                formBuilder.append(space10).append("<el-input v-model=\"ruleForm.").append(camelCaseName).append("\" autocomplete=\"off\"></el-input>\n");
            }
            formBuilder.append(space8).append("</el-form-item>\n");
        }
        String rules = generateRules(tableColumns);
        String ruleForm = generateRuleForm(tableColumns);
        Map<String, Object> map = new HashMap<>();
        map.put("tableColumn", tableColumnBuilder.toString());
        map.put("formItem", formItemBuilder.toString());
        map.put("upperEntityName", upperEntityName);
        map.put("lowerEntityName", lowerEntityName);
        map.put("rules", rules);
        map.put("ruleForm", ruleForm);
        String format = StrUtil.format(FileUtil.readUtf8String(basePath + "/springboot/src/main/resources/templates/vue.template"), map);
        FileUtil.writeString(format, basePath + "/springboot/vue/src/views/" + upperEntityName + ".vue", "UTF-8");
//        System.out.println(upperEntityName + ".vue生成成功！");

    }

    private static String generateRules(List<TableColumn> tableColumns) {
        StringBuilder rulesBuilder = new StringBuilder();
        rulesBuilder.append("rules: {\n");
        for (int i = 0; i < tableColumns.size(); i++) {
            String fieldName = tableColumns.get(i).getName();
            String camelCaseName = StrUtil.toCamelCase(fieldName);
            if (fieldName.contains("id") || fieldName.contains("time") || fieldName.contains("date")) {
                continue;
            }
            rulesBuilder.append("  ").append(camelCaseName).append(": [\n");
            rulesBuilder.append("    { required: true, message: '请输入', trigger: 'blur' }\n");
            rulesBuilder.append("  ],\n");
        }
        rulesBuilder.append("}");

        return rulesBuilder.toString();
    }

    private static String generateRuleForm(List<TableColumn> tableColumns) {
        StringBuilder rulesBuilder = new StringBuilder();
        rulesBuilder.append("ruleForm: {\n");

        for (int i = 0; i < tableColumns.size(); i++) {
            String fieldName = tableColumns.get(i).getName();
            String camelCaseName = StrUtil.toCamelCase(fieldName);
            if (fieldName.equals("id") || fieldName.contains("time") || fieldName.contains("date")) {
                continue;
            }
            rulesBuilder.append("  ").append(camelCaseName).append(": '',");
            rulesBuilder.append("\n");
        }
        rulesBuilder.append("}");
        return rulesBuilder.toString();
    }

    private static void createMenu(CodeGeneratorDto dto) throws Exception {
        String lowerEntityName = StrUtil.toCamelCase(dto.getTableName().replace("sys_", "").replace("t_", ""));
        String upperEntityName = StrUtil.upperFirst(lowerEntityName);
        DataSource ds = getDatasource(dto);
        //生成菜单
        String delSql = "DELETE from sys_menu where name = ?";
        Db.use(ds).execute(delSql, dto.getModelName());
        String createSql = StrUtil.format("INSERT INTO `sys_menu` (`name`, `path`, `icon`, `page_path`, `sort_num`) VALUES ('{}', '{}', '{}', '{}', {})",
                dto.getModelName(), "/" + lowerEntityName, "el-icon-menu", upperEntityName, 999);
        Db.use(ds).execute(createSql);
        System.out.println(lowerEntityName + "菜单生成成功！");
    }


    /**
     * 获取数据库表字段
     *
     * @param dto
     * @return
     * @throws SQLException
     */
    private static List<TableColumn> getTableColumns(CodeGeneratorDto dto) throws SQLException {
        DataSource ds = getDatasource(dto);
        String sql = "SELECT table_name,column_name,data_type, column_comment FROM information_schema.COLUMNS WHERE table_schema = ? and table_name = ?";
        String newUrl = url + dto.getDataSource();
        String schema = newUrl.substring(newUrl.lastIndexOf("/") + 1);
        List<Entity> list = Db.use(ds).query(sql, schema, dto.getTableName());
        List<TableColumn> columns = CollUtil.newArrayList();
        for (Entity entity : list) {
            TableColumn tableColumn = new TableColumn();
            String columnName = entity.getStr("column_name");
            tableColumn.setName(columnName);
            String comment = entity.getStr("column_comment");
            tableColumn.setComment(comment);
            columns.add(tableColumn);
        }
        return columns;
    }

    private static DataSource getDatasource(CodeGeneratorDto dto) {
        return new SimpleDataSource(url + dto.getDataSource(), username, dto.getPassword());
    }
}